#pragma once

#include "memory.h"
#include <cmath>

#define qword unsigned long long
#define dword unsigned int
#define word unsigned short
#define byte unsigned char
#define real4 float
#define real8 double

union VREG
{
	qword qvalues[8];
	real8 ddvalues[8];
	dword dvalues[16];
	real4 fvalues[16];
	word wvalues[32];
	byte bvalues[64];
};

// Flags Definition
#define RUNNING 0x01
#define DEBUG 0x02
#define ERROR 0x04
#define PROTECTED 0x08
#define CARRY 0x10
#define ZERO 0x20
#define POS 0x40
#define NEG 0x80
#define SUPER 0x100
#define AVX 0x200
#define IT_EN 0x400
#define IT_ON 0x800
#define FLT_ON 0x1000
#define IP_L 0x2000
#define IP_H 0x4000
#define DMA_ON 0x8000 // Direct Memory Access

enum ADDR
{
	Code,
	Data,
	Base,
	Stack,
	SI,
	DI,
	ES1,
	ES2
};
enum SPEC
{
	Flag = 8,
	LDTR,
	IDTR,
	TSSR,
	Count,
	Time,
	GDT_Count
};
enum DTYPE
{
	BYTE = 1,
	WORD,
	DWORD,
	QWORD,
	REAL4,
	REAL8
};
enum DIRECTION
{
	IN_MEM,
	OUT_MEM
};
enum OPERATION
{
	RO,
	WO,
	RW,
	RX,
	RWX
};

void set_valueV(VREG value, byte reg);
void set_valueD(real8 value, byte reg);
void set_valueF(real4 value, byte reg);
void set_valueI(qword value, byte reg);

inline void read_mem(qword address, byte reg, byte size);
inline void write_mem(qword address, byte reg, byte size);
inline void changeFlag(byte reg);